package notes.java.juc.demo;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 用Lock锁解决问题：普通按例的生产者与消费者
 * 
 * 会出现问题，当生产者与消费者数量不同时，
 * 
 * 生产者多，消费者少就会出现虚假唤醒问题，product出现了大于10了。
 * 生产者少，消费者多就出现了虚假唤醒问题，product出现了负数
 *
 */
public class J9_TestProductorAndCustomerUseLock {

	public static void main(String[] args) {
		Clerk2 clerk2 = new Clerk2();

		new Thread(new Productor2(clerk2)).start();
//		new Thread(new Productor2(clerk2)).start();
		new Thread(new Customer2(clerk2)).start();
		new Thread(new Customer2(clerk2)).start();
	}

}

// 生产者
class Productor2 implements Runnable {
	private Clerk2 clerk2;

	public Productor2(Clerk2 clerk2) {
		super();
		this.clerk2 = clerk2;
	}

	@Override
	public void run() {
		while (true) {
			try {
				clerk2.buy();
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class Customer2 implements Runnable {
	private Clerk2 clerk2;

	public Customer2(Clerk2 clerk2) {
		super();
		this.clerk2 = clerk2;
	}

	@Override
	public void run() {
		while (true) {
			try {
				Thread.sleep(100);
				clerk2.sale();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

/**
 * 店员
 *
 */
class Clerk2 {
	private int product = 0; // 产品数量
	
	// 加锁
	private Lock lock = new ReentrantLock();
	private Condition condition = lock.newCondition();

	// 进货
	public void buy() throws InterruptedException {
		lock.lock(); // 加锁
		try{
			while (product >= 10) {
				
				System.out.println("2已经满了...");
				condition.await();
			}
			
			System.out.println("2进货..." + product++);
			condition.signalAll();
		}finally {
			lock.unlock();
		}
		
	}

	// 卖货
	public void sale() throws InterruptedException {
		try{
			lock.lock();
			while (product <= 0) {
				System.out.println("2卖完了...");
				condition.await();
			} 
			
			System.out.println("2卖货..." + product--);
			condition.signalAll();
		} finally {
			lock.unlock();
		}
	}
}